
#include <stdio.h>
#include <stdint.h>
#include <math.h>

#include "iot_adc.h"
#include "iot_errno.h"
#include "mq135.h"

#define MQ135_ADC_CHANNEL 0   // RK2206 只有一个 ADC 通道
#define RL 1.0f               // RL电阻值（单位 kΩ）
#define CAL_PPM 400.0f        // 校准用的默认 ppm
#define CAL_RSRO_RATIO 3.6f   // 来自MQ135的特性曲线

static float g_r0 = 1.0f;     // 校准得到的R0值

// 获取当前电压
static float get_voltage(void)
{
    unsigned int val = 0;
    int ret = IoTAdcGetVal(MQ135_ADC_CHANNEL, &val);
    if (ret != IOT_SUCCESS) {
        printf("[MQ135]  ADC读取失败\n");
        return 0.0f;
    }

    float voltage = val * 3.3f / 1024.0f;
    printf("[MQ135] ADC原始值: %u, 电压: %.3f V\n", val, voltage);
    return voltage;
}

// /***************************************************************
// * 函数名称: mq135_init
// * 说    明: 初始化MQ135传感器，配置ADC
// * 参    数: 无
// * 返 回 值: 无
// ***************************************************************/
void mq135_init(void)
{
    int ret = IoTAdcInit(MQ135_ADC_CHANNEL);
    if (ret == IOT_SUCCESS) {
        printf("[MQ135] ADC初始化成功 (通道: %d)\n", MQ135_ADC_CHANNEL);
    } else {
        printf("[MQ135]  ADC初始化失败\n");
    }
}

// 校准
void mq135_calibrate(void)
{
    float voltage = get_voltage();
    if (voltage <= 0.0f) {
        printf("[MQ135] 电压异常，无法校准\n");
        return;
    }

    float rs = (5.0f - voltage) / voltage * RL;
    g_r0 = rs / CAL_RSRO_RATIO;

    printf("[MQ135]  校准完成 -> Rs: %.3f kΩ, R0: %.3f kΩ\n", rs, g_r0);
}

// /***************************************************************
// * 函数名称: mq135_calc_ppm
// * 说    明: 根据ADC原始值计算PPM（气体浓度）
// * 参    数: rawValue：ADC读取到的原始值
// * 返 回 值: 计算后的PPM值
// ***************************************************************/
float mq135_calc_ppm(uint16_t raw)
{
    float voltage = raw * 3.3f / 1024.0f;
    float rs = (5.0f - voltage) / voltage * RL;
    float ratio = rs / g_r0;
    float ppm = 116.6f * powf(ratio, -2.77f);

    printf("[MQ135] --Rs: %.3f, Ratio: %.3f, PPM: %.2f\n", rs, ratio, ppm);
    return ppm;
}
// /***************************************************************
// * 函数名称: mq135_read_data
// * 说    明: 读取MQ135传感器数据并计算气体浓度
// * 参    数: ppm：存放计算后的气体浓度（单位：ppm）
// * 返 回 值: 无
// ***************************************************************/
void mq135_read_data(double *ppm)
{
unsigned int raw = 0;
     int ret, retry = 0;

    ret = IoTAdcGetVal(MQ135_ADC_CHANNEL, &raw);
    //多次尝试读取数据，如果失败则延迟20ms再重试
   for(retry = 0; retry < 5; retry++){
        ret = IoTAdcGetVal(MQ135_ADC_CHANNEL, &raw);
        if (ret == IOT_SUCCESS) break;
        printf("Read failed, retry %d\n", retry + 1);
        LOS_Msleep(20);
     }
    //超过三次返回异常值
    if (retry >= 3) {
     printf("MQ135 read failed after retries.\n");
     *ppm = -100.0;
     return;
    }

    if (IoTAdcGetVal(MQ135_ADC_CHANNEL, &raw) != IOT_SUCCESS) {
     printf("[MQ135] ADC获取失败\n");
     *ppm = 0;
     return;
     }

    printf("[MQ135]读取成功 -> Raw: %u\n", raw);
    *ppm = mq135_calc_ppm(raw);
}

